package com.sharemedia.managers
{
	import com.sharemedia.consts.AppConst;
	import com.sharemedia.vos.Track;
	import com.sharemedia.vos.TrackInfo;
	import com.sharemedia.vos.TrackPacket;
	
	import mx.collections.ArrayCollection;
	import mx.collections.ArrayList;
	import mx.utils.ObjectUtil;

	public class TrackBuffer2
	{
		private var tracks:Vector.<Track> = new Vector.<Track>();
		public function TrackBuffer2()
		{
		}
		
		public function addPacket(packet:TrackPacket):Boolean
		{
			var trackPosition:Number = currentTrack ? tracks.indexOf(currentTrack) : 0;
			var track:Track = findTrack(packet);
			if(packet.info)
			{
				if(!track.info || track.info.name != packet.info.name || packet.info.artist !=  packet.info.artist)
					track.info = new TrackInfo(packet.info.name, packet.info.artist);
				
				if(track.rating != packet.info.rating)
					track.rating = packet.info.rating;
				
				if(track.length != packet.info.length)
					track.length = packet.info.length;
			}
			track.packets.push(packet);
			track.packets.sort(sortFunc);
			
			var index:int = tracks.indexOf(track);
			// synchronize
			if(track.packets.length == AppConst.BUFFER_SIZE && trackPosition < index)
			{
				currentTrack = tracks[index];
				packetPosition = 0;
			}
			
			return getAvailableBufferSize() >= AppConst.BUFFER_SIZE;
		}
		
		private var currentTrack:Track;

		private var packetPosition:Number = 0;
		public function extractPacket():TrackPacket
		{
			var trackPosition:Number = currentTrack ? tracks.indexOf(currentTrack) : 0;
			
			if(tracks.length > trackPosition)
			{
				var track:Track = tracks[trackPosition];
				if(track.packets.length > packetPosition)
				{
					var packet:TrackPacket = track.packets[packetPosition];
					packetPosition++;
					
					clearBuffer();
					
					return packet;
				}
				else
				{
					packetPosition = 0;
					trackPosition++;
					return extractPacket();
				}
			}
			
			return null;
		}
		
		public function getCurrentTrack():Track
		{
			return currentTrack;
		}
		
		public function getPlayedTracks():Array
		{
			var trackPosition:Number = currentTrack ? tracks.indexOf(currentTrack) : 0;
			var result:Array = new Array();
			for (var i:int = 0; i < trackPosition; i++) 
			{
				if(tracks[i].info)
					result.unshift(tracks[i]);
			}
			
			return result;
		}
				
		
		private function getAvailableBufferSize():Number
		{
			var trackPosition:Number = currentTrack ? tracks.indexOf(currentTrack) : 0;
			var counter:uint = 0;
			
			if(trackPosition && currentTrack.packets.length > packetPosition)
				counter += currentTrack.packets.length - packetPosition;
		
			for (var i:int = trackPosition+1; i < tracks.length; i++) 
			{
				var track:Track = tracks[i];
				counter += track.packets.length;
			}
			
			return counter;
		}
		
		private function findTrack(packet:TrackPacket):Track
		{
			for each (var track:Track in tracks) 
			{
				if(track.broadcastUid == packet.broadcastUid)	
					return track;
			}
			
			var newTrack:Track = new Track(packet.trackUid);
			newTrack.broadcastUid = packet.broadcastUid;
			tracks.push(newTrack);
			
			return newTrack;
		}
		
		public var bufferSize:Number = AppConst.SOUND_CHUNK_SIZE*AppConst.BUFFER_SIZE*2;
		private function clearBuffer():void
		{
			var size:Number = 0;
			for (var i:int = tracks.length-1; i >= 0 ; i--) 
			{
				var track:Track = tracks[i];
				
				if(size + track.packets.length*AppConst.SOUND_CHUNK_SIZE > bufferSize)
				{
					var index:Number = track.packets.length - (bufferSize - size)/AppConst.SOUND_CHUNK_SIZE;
					track.packets.splice(0, index);
					
					if(track.packets.length == 0)
						return;
				}
				
				size += track.packets.length*AppConst.SOUND_CHUNK_SIZE;
			}
		}
		
		private function sortFunc(a:TrackPacket, b:TrackPacket):Number
		{
			return ObjectUtil.numericCompare(a.sendTime, b.sendTime);
		}
		
	}
}